﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting.Messaging;
using System.Reflection;
using System.Linq.Expressions;

namespace Platform.Storage.Redis.Hash
{

	public static class MethodCassMessageExtensions
	{

		internal static string GetPropertyName( this IMethodCallMessage msg )
		{
			return msg.MethodName.Substring( 4 );
		}

		internal static bool IsSetProperty( this IMethodCallMessage msg )
		{
			return msg != null
				&& msg.InArgCount == 1
				&& msg.MethodBase.IsSpecialName
				&& msg.MethodName.StartsWith( "set_" );
		}

		internal static bool IsGetProperty( this IMethodCallMessage msg )
		{
			if ( msg.InArgCount == 0
				&& msg.MethodName.StartsWith( "get_" )
				&& msg.MethodBase.IsSpecialName )
			{
				MethodInfo method = msg.MethodBase as MethodInfo;

				return method != null
					&& ( method.ReturnType.Equals( typeof( String ) ) || method.ReturnType.IsValueType );
			}
			return false;
		}

		internal static ReturnMessage Return<T1, T2, TReturn>( this IMethodCallMessage msg, Func<T1,T2,TReturn> f, T1 p1, T2 p2 )
		{
			return msg.Return<TReturn>( () => f( p1, p2 ) );
		}

		internal static ReturnMessage Return<TReturn>( this IMethodCallMessage msg, Func<TReturn> execute)
		{
			try
			{
				return new ReturnMessage( execute(), null, 0, msg.LogicalCallContext, msg );
			}
			catch ( Exception ex )
			{
				return new ReturnMessage( ex, msg );
			}
		}

		internal static ReturnMessage ReturnVoid( this IMethodCallMessage msg, Action execute )
		{
			try
			{
				execute();
				return new ReturnMessage( null, null, 0, msg.LogicalCallContext, msg );
			}
			catch ( Exception ex )
			{
				return new ReturnMessage( ex, msg );
			}
		}

		internal static bool HasOnlySafeType( this IMethodCallMessage msg )
		{
			Type strType = typeof(String);
			return msg.MethodBase.GetParameters().All( p => p.ParameterType.IsValueType || p.ParameterType.Equals( strType ) );
		}

		internal static bool IsReadValuesMethod( this IMethodCallMessage msg )
		{
			return msg.InArgCount == 0
				&& msg.MethodName == "ReadValues";
		}

		internal static bool IsCommitMethod( this IMethodCallMessage msg )
		{
			return msg.InArgCount == 0
				&& msg.MethodName == "Commit";
		}

		public static int Increment<T>( this T hash, Expression<Func<T, object>> property, int step = 1 )
			where T : IHashObject
		{
			return hash.Increment( "Total", step );
		}

		public static int Decrement<T>( this T hash, Expression<Func<T, object>> property, int step = 1 )
			where T : IHashObject
		{
			return hash.Increment( "Total", step * -1 );
		}
	}
}
